﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Xml;
using System.IO;
using System.Threading;
using System.Reflection;
using Comm.PublicClass;
using WsProtocol.PublicClass;
using System.Runtime.Serialization.Formatters.Binary;
using WsProtocol.IEC62056.CosemACSE;


namespace WsProtocol.IEC62056.DLL
{
    //  62056链路层实现  hxh/wx 2018-5
    public class Analysis62056
    {
        private const string framehead = "7E";  //帧头
        private const string frametail = "7E";   //帧尾
        private const string CLLCHead = "E6E600";  //客户端LLC帧头
        private const string SLLCHead = "E6E700";  //服务端LLC帧头
        //帧格式域类
        [Serializable]
        public class TFormatL
        {
            private string frameL = string.Empty;  //帧内格式域长度

            public int L_lenData;  //用户数据长度，(不含2 个0x7e）
            public EnuSPLIT F_SPLIT = EnuSPLIT.end;  //分帧标志位 1分割 0结束
            public string F_FrameType = "1010";  //帧类型， 恒为A（1010）

            //组帧
            public string GetFormatValue(string addr, string parameter,TForamtC C)
            {
                int L = addr.Length / 2    //目的及源地址长度
                      + 1  //控制码1字节                     
                      + 2  //FCS 2字节
                      + 2;  //长度域本身占2字节
                
                   
                if (!string.IsNullOrEmpty(parameter))
                {
                    L = L + 2 + parameter.Length / 2;  //HCS长度和链路用户数据长度

                   if (C.C_FrameType != EnuFrameType.SNRM)  //建立链路层连接时有用户数据，但无LLC帧头
                       L = L + CLLCHead.Length / 2;//LLc帧头长度
                }

                //转为二进制
                string ilength = F_FrameType + ((int)F_SPLIT).ToString()
                                 + MyConvert.DecToBin(L.ToString(), 11);
                ilength = MyConvert.BinToHex(ilength, 4);

                return ilength;
            }

            //解帧
            public void AnalizeData(ref string avalue)
            {
                frameL = avalue.Substring(0, 4);  //长度
                // frameL = ProtocolRelated.ChangeAddress(frameL);
                string tmpl = MyConvert.HexToBin(frameL).PadLeft(16, '0');  //转二进制
                F_FrameType = tmpl.Substring(0, 4);  //帧类型
                tmpl = tmpl.Substring(4);
                F_SPLIT = (EnuSPLIT)int.Parse(tmpl.Substring(0, 1));  //分帧标志
                L_lenData = Convert.ToInt32(MyConvert.BinToDec(tmpl.Substring(1)));  //帧长度
                avalue = avalue.Substring(4);
            }

            //获取帧内数据
            public string GetFrameData()
            {
                return frameL;
            }

            //获取拆帧信息
            public string GetInfo()
            {
                string rs = "帧内数据"
                          + "->"
                          + GetFrameData()
                          + " ["
                          + "帧类型"
                          + ":"
                          + F_FrameType
                          + "; "
                          + "分帧标志"
                          + ":"
                          + F_SPLIT
                          + "; "
                          + "帧长度"
                          + ":"
                          + L_lenData
                          + "]";
                return rs;
            }
        }


        //地址域类
        [Serializable]
        public class TFormatAddr
        {
            private string frameAddr = string.Empty;  //帧内地址部分

           // public string SAddr; //服务端物理地址
            public int SAddr_Lower;//服务低端物理地址
            public int SAddr_High = 1;//服务高端物理地址
            public int SAddr_LEN = 4;  //服务端逻辑地址长度，默认4字节;
            public string SAddr_LOGIC;  //服务端逻辑地址

            public int CAddr = 1; //客户端地址
            public string CAddr_LOGIC; //客户端逻辑地址

            //组帧
            public string GetFormatValue(ref string errinfo)  //目的地址+源地址（客户端）
            {
                //客户端逻辑地址,最低位固定为1
                
                CAddr_LOGIC = MyConvert.DecToHex(((CAddr << 1) + 1).ToString(), 2);

                SAddr_LOGIC = string.Empty;            
                switch (this.SAddr_LEN)
                {
                    case 1:
                        byte byads = (byte)SAddr_Lower;
                        byads = (byte)((byte)(byads << 1) | 0x01);
                        SAddr_LOGIC = string.Format("{0:X2}", byads);
                        break;
                    case 2://一字节高端HDLC地址和一字节低端HDLC地址
                        UInt16 uads16 = (UInt16)SAddr_High;
                        uads16 = (UInt16)(uads16 << 9);
                        uads16 = (UInt16)(uads16 | ((byte)SAddr_Lower << 1));
                        uads16 = (UInt16)(uads16 & 0xFEFF + 1);

                        SAddr_LOGIC = string.Format("{0:X4}", uads16);
                        break;
                    case 4://两字节高端HDLC地址和两字节低端HDLC地址
                        UInt16 uads16_u = (UInt16)((UInt16)SAddr_High << 1);
                        UInt16 uads16_1 = (UInt16)((uads16_u & 0xFF00) << 1);
                        UInt16 uads16_2 = (UInt16)((uads16_u & 0x00FF));

                        UInt16 uads16_l = (UInt16)((UInt16)SAddr_Lower << 1);
                        UInt16 uads16_3 = (UInt16)((uads16_l & 0xFF00) << 1);
                        UInt16 uads16_4 = (UInt16)((uads16_l & 0x00FF) + 1);

                        UInt32 uads32 = ((UInt32)uads16_1 << 16) | ((UInt32)uads16_2 << 16) | ((UInt32)uads16_3) | ((UInt32)uads16_4);
                        SAddr_LOGIC = string.Format("{0:X8}", uads32);
                        break;
                }
                return SAddr_LOGIC + CAddr_LOGIC;
            }

           

            //解帧
            public void AnalizeData(ref string avalue)  //目的地址(客户端)+源地址
            {
                frameAddr = string.Empty;
                string HexCAddr = AnalizeAddr(ref avalue);
                CAddr_LOGIC = HexCAddr;
                CAddr = int.Parse(MyConvert.HexToDec(HexCAddr));

                string HexSAddr = AnalizeAddr(ref avalue);

                string tmpSaddr = HexSAddr;
                SAddr_LEN = HexSAddr.Length / 2;
                SAddr_LOGIC = HexSAddr;
                if (HexCAddr.Length / 2 > HexSAddr.Length) //调换
                {
                    SAddr_LEN = HexCAddr.Length / 2;
                    tmpSaddr = HexCAddr;
                    CAddr = int.Parse(MyConvert.HexToDec(HexSAddr));
                    CAddr_LOGIC = HexSAddr;

                    SAddr_LOGIC = HexCAddr;                    
                }
                switch (SAddr_LEN)
                {
                    case 1:
                        SAddr_Lower = int.Parse(MyConvert.HexToDec(tmpSaddr)); 
                        break;
                    case 2:
                        SAddr_High = int.Parse(MyConvert.HexToDec(tmpSaddr.Substring(0, 2)));
                        SAddr_Lower = int.Parse(MyConvert.HexToDec(tmpSaddr.Substring(2, 2))); 
                        break;
                    case 4:
                        SAddr_High = int.Parse(MyConvert.HexToDec(tmpSaddr.Substring(0, 4)));
                        SAddr_Lower = int.Parse(MyConvert.HexToDec(tmpSaddr.Substring(4, 4))); 
                        break;
                }
                
            }

            private string AnalizeAddr(ref string avalue)
            {

                int i = 1;
                string strByte = avalue.Substring(0, 2);
                frameAddr += strByte;
                UInt16 uads16_u = Convert.ToUInt16(strByte, 16);
                
                string tmpCAddrP = MyConvert.DecToBin((uads16_u >> 1).ToString(), 8);
                string tmpCAddrL = string.Empty;
                string tmpCAddr = string.Empty;
                avalue = avalue.Substring(2);
                while ((uads16_u & 1) != 1)
                {                    
                    strByte = avalue.Substring(0, 2);
                    frameAddr += strByte;
                    uads16_u = Convert.ToUInt16(strByte, 16);
                    string ds16_u = MyConvert.DecToBin((uads16_u >> 1).ToString(), 8);
                    if (i == 0)
                    {
                        tmpCAddrP = tmpCAddrP + ds16_u;//第一个字节直接右移一位
                        i++;
                    }
                    else
                    {
                        tmpCAddrL = ds16_u.Substring(1); //第二个字节只取7bit,再跟第一个字节相拼前面补一个0位
                        tmpCAddr = tmpCAddr + "0" + tmpCAddrP + tmpCAddrL;
                        tmpCAddrP = tmpCAddrL = string.Empty;
                        i = 0;
                    }                 
                    avalue = avalue.Substring(2);
                }
                int len = 2;
                if (string.IsNullOrEmpty(tmpCAddr))
                    tmpCAddr = tmpCAddrP;
                if (tmpCAddr.Length > 8)//2字节
                    len = 4;
                if (tmpCAddr.Length > 16) //4字节
                    len = 8;

                return MyConvert.BinToHex(tmpCAddr, len); 

            }

           
            //获取帧内数据
            public string GetFrameData()
            {
                return frameAddr;
            }

            //获取拆帧信息
            public string GetInfo()
            {
                string rs = "帧内数据"
                          + "->"
                          + GetFrameData()
                          + " ["
                          + "服务低端物理地址"
                          + ":"
                          + SAddr_Lower
                          + "; "
                          + "服务高端物理地址"
                          + ":"
                          + SAddr_High
                          + "; "
                          + "服务端逻辑地址长度"
                          + ":"
                          + SAddr_LEN
                          + "; "
                          + "服务端逻辑地址"
                          + ":"
                          + SAddr_LOGIC
                          + "; "
                          + "客户端地址"
                          + ":"
                          + CAddr
                          + "; "
                          + "客户端逻辑地址"
                          + ":"
                          + CAddr_LOGIC
                          + "]";
                return rs;
            }
        }

        //控制码类
        [Serializable]
        public class TForamtC
        {
            private string frameC = string.Empty;  //帧内控制码

            public int RRR = 0;   //为接收帧计数，
            public int SSS = -1;   //为发送帧计数
            public EnuFrameType C_FrameType;   //帧类型名称
            public EnuPBit PBit = EnuPBit.PRE; //查询位
            public EnuFBit FBit; //结束位

            //组帧
            public string GetFormatValue()
            {
               // SSS++;

                string strFrameType = string.Empty;
                switch (C_FrameType)
                {
                    case EnuFrameType.I:
                        strFrameType = "RRRP/FSSS0";
                        break;
                    case EnuFrameType.RR:
                        strFrameType = "RRRP/F0001";
                        break;
                    case EnuFrameType.RNR:
                        strFrameType = "RRRP/F0101";
                        break;
                    case EnuFrameType.SNRM:
                        strFrameType = "100P0011";
                        break;
                    case EnuFrameType.DISC:
                        strFrameType = "010P0011";
                        break;
                    case EnuFrameType.UI:
                        strFrameType = "000P/F0011";
                        break;
                }
                if (strFrameType == null) return null;

                // 替换接收序号
                string strRecNum = MyConvert.DecToBin(RRR.ToString(), 3);
                strFrameType = strFrameType.Replace("RRR", strRecNum);
                // 替换发送序号
                if (SSS < 0) //组帧时发送序号不可能小于0
                    SSS = 0;
                string strSendNum = MyConvert.DecToBin(SSS.ToString(), 3);
                
                strFrameType = strFrameType.Replace("SSS", strSendNum);

                // 替换PF
                string strPF = ((int)PBit).ToString();
                strFrameType = strFrameType.Replace("P/F", strPF);
                strFrameType = strFrameType.Replace("P", strPF);
                strFrameType = strFrameType.Replace("F", strPF);

                // 转成字节               
                frameC = MyConvert.BinToHex(strFrameType).PadLeft(2, '0');
                return frameC;
            }

            //解帧
            public void AnalizeData(ref string avalue, ref string errinfo)
            {
                frameC = avalue.Substring(0, 2);  //控制码

                string tmpbin = MyConvert.HexToBin(frameC).PadLeft(8, '0');  //转为二进制

                C_FrameType = AnalyseFrameType(tmpbin);
                FBit = (EnuFBit)int.Parse(tmpbin.Substring(3, 1));
                switch (C_FrameType)
                {
                    case EnuFrameType.I:  //返回I帧   R R R P/F S S S 0  
                        RRR = int.Parse(MyConvert.BinToDec(tmpbin.Substring(0, 3)));
                        SSS = int.Parse(MyConvert.BinToDec(tmpbin.Substring(4, 3)));
                        break;
                    case EnuFrameType.RR:  //R R R P/F 0 0 0 1 返回RR帧
                    case EnuFrameType.RNR: //返回RNR帧   R R R P/F 0 1 0 1
                        RRR = int.Parse(MyConvert.BinToDec(tmpbin.Substring(0, 3)));
                        break;
                }
                avalue = avalue.Substring(2);
            }

            /// <summary>
            /// 分析帧类型
            /// </summary>
            /// <param name="strFrameType">2位BCD码</param>
            /// <returns></returns>
            private EnuFrameType AnalyseFrameType(string strTypeBin)
            {
                if (strTypeBin.Substring(7, 1) == "0")
                {
                    return EnuFrameType.I;
                }

                if (strTypeBin.Substring(4, 4) == "0001")
                {
                    return EnuFrameType.RR;
                }

                if (strTypeBin.Substring(4, 4) == "0101")
                {
                    return EnuFrameType.RNR;
                }

                if (strTypeBin.Substring(4, 4) == "0011")
                {
                    if (strTypeBin.Substring(0, 3) == "100")
                    {
                        return EnuFrameType.SNRM;
                    }
                    if (strTypeBin.Substring(0, 3) == "010")
                    {
                        return EnuFrameType.DISC;
                    }
                    if (strTypeBin.Substring(0, 3) == "011")
                    {
                        return EnuFrameType.UA;
                    }
                    if (strTypeBin.Substring(0, 3) == "000")
                    {
                        return EnuFrameType.UI;
                    }
                }

                if (strTypeBin.Substring(4, 4) == "1111" && strTypeBin.Substring(0, 3) == "000")
                {
                    return EnuFrameType.DM;
                }

                if (strTypeBin.Substring(4, 4) == "0111" && strTypeBin.Substring(0, 3) == "100")
                {
                    return EnuFrameType.FRMR;
                }

                throw new Exception("帧类型分析异常");
            }



            //获取帧内数据
            public string GetFrameData()
            {
                return frameC;
            }

           

            //获取拆帧信息
            public string GetInfo()
            {
                string rs = "帧内数据"
                          + "->"
                          + GetFrameData()
                          + " ["
                          + "接收帧计数"
                          + ":"
                          + RRR
                          + "; "
                          + "发送帧计数"
                          + ":"
                          + SSS
                          + "; "
                          + "帧类型"
                          + ":"
                          + C_FrameType.ToString()
                          + "]";
                return rs;
            }
        }

        //帧结构
        [Serializable]
        public class TFormat62056 : PtlFormat
        {
            public string Head;    //帧头
            public TFormatL FormatL; //帧格式域            
            public TFormatAddr Addr;  //地址域
            public TForamtC C;       //控制码域
            public TForamtC LastC;   //上一帧发送控制码域，且只在链路层分帧里才会有赋值，其他情况下都为NULL
            public string HCS;      //帧头校验
            public string LLCHead;  //LLC帧头
            public string ApduData; //Apdu用户数据内容          
            public CosemApdu Apdu;  //Apdu数据处理类 
            public string FCS;       //帧校验
            public string Tail;      //帧尾


            #region 47协议  udp相关参数
            public string udpVer = "0001";  //版本号
            public string udpCAddr;  //UDP客户端地址
            public string udpSAddr;  //UDP服务端地址

            #endregion


            public TFormat62056()
            {
                FormatL = new TFormatL();
                C = new TForamtC();
                Addr = new TFormatAddr();
                Apdu = new CosemApdu();
            }
           

            //判断是否需要返回
            public bool NeedReturn()
            {
                if (!string.IsNullOrEmpty(udpCAddr))  //47协议
                    return true;
                
                switch (Addr.SAddr_LEN)
                {  //广播地址或无地址
                    case 1:
                        if (Addr.SAddr_Lower == 0x7F || Addr.SAddr_Lower == 0x00)
                            return false;
                        break;
                    case 2:
                        if (Addr.SAddr_High == 0x7F || Addr.SAddr_High == 0x00 ||
                            Addr.SAddr_Lower == 0x7F || Addr.SAddr_Lower == 0x00)
                            return false;
                        break;
                    case 4:
                        if (Addr.SAddr_High == 0x3FFF || Addr.SAddr_High == 0x0000 || 
                            Addr.SAddr_Lower == 0x3FFF || Addr.SAddr_Lower == 0x0000)
                            return false;
                        break;
                }

                //判断客户端地址，如果是预连接不需要返回
                if (Addr.CAddr == 102)
                    return false;

                return true;
            }

            public bool CheckAddress()
            {
                bool NeedR = NeedReturn();
                if (Addr.CAddr == 0x00 || Addr.CAddr == 0x7F)
                {
                    return false;//client address is NO_STATION address //client address is ALL_STATION address
                }
                if (C.C_FrameType == EnuFrameType.I || NeedR)
                {
                    switch (Addr.SAddr_LEN)
                    {
                        case 1:
                            if (0x7F == Addr.SAddr_Lower)
                            {
                                return false;
                            }
                            break;
                        case 2:
                            if (0x7F == Addr.SAddr_Lower || 0x7F == Addr.SAddr_High)
                            {
                                return false;
                            }
                            break;
                        case 4:
                            if (0x3FFF == Addr.SAddr_Lower || 0x3FFF == Addr.SAddr_High)
                            {
                                return false;
                            }
                            break;
                        default: break;
                    }

                }
                if (NeedR)
                {
                    if (0x00 == Addr.SAddr_High || (Addr.SAddr_LEN > 1 && 0x00 == Addr.SAddr_Lower))//server address is NO_STATION address
                    {
                        return false;
                    }
                }
                if (Addr.SAddr_High >= 0x02 && Addr.SAddr_High <= 0x0F)
                {
                    return false;
                }

                if (Addr.SAddr_Lower >= 0x01 && Addr.SAddr_Lower <= 0x0F)
                {
                    return false;
                }

                return true;
            }

            
            private void GetApduInfo(List<string> infolst)
            {
                foreach (CosemObject oi in Apdu.OIList)
                {
                    //Application.
                    ShowOIValue(infolst, oi);
                }
            }

            private void ShowOIValue(List<string> infolst, CosemObject oiobj)
            {
                infolst.Add("/******************data*************************/");
                infolst.Add(("服务原语").PadRight(12) + Apdu.rwtype);
                infolst.Add(("结果").PadRight(16) + oiobj.result);
                ShowEleValue(infolst, oiobj.DataNode);
                
                infolst.Add("/**************************************************/");
            }

            private void ShowEleValue(List<string> infolst, ElementData eleobj)
            {
                infolst.Add(("数据").PadRight(16) + eleobj.FrameValue + "[" + eleobj.DataType + "][" + eleobj.DataLen + "]   " + "值" + eleobj.ReadValue);
                
                for (int i = 0; i < eleobj.eleNodeList.Count; i++)
                {
                    ShowEleValue(infolst, eleobj.eleNodeList[i]);
                }

            }



            /// <summary>
            /// 获取分解后的描述信息
            /// </summary>
            /// <returns></returns>
            public override List<string> GetInfo()
            {
                List<string> infolst = new List<string>();
                infolst.Add(("帧头:").PadRight(16) + Head);
                infolst.Add(("长度域:").PadRight(16) + FormatL.GetInfo());
                infolst.Add(("地址域:").PadRight(16) + Addr.GetInfo());
                infolst.Add(("控制域:").PadRight(16) + C.GetInfo());
                infolst.Add(("帧头校验:").PadRight(14) + HCS);
                infolst.Add(("LLC帧头:").PadRight(16) + LLCHead);
                //  infolst.Add("分帧格式域:    " + SplitData.GetFrameData());
                infolst.Add(("链路用户数据:").PadRight(16) + SplitStr(ApduData));

                GetApduInfo(infolst);

                infolst.Add(("帧校验:").PadRight(16) + FCS);
                infolst.Add(("帧尾:").PadRight(16) + Tail);
                return infolst;
            }

            /// <summary>
            /// 以空格拆分字符串。
            /// </summary>
            /// <param name="source"></param>
            /// <returns></returns>
            public string SplitStr(string source)
            {
                if (string.IsNullOrEmpty(source))
                    return string.Empty;
                string stringOut = string.Empty;
                int length = source.Length / 2;

                for (int i = 0; i < length; i++)
                {
                    stringOut += source.Substring(i * 2, 2) + " ";
                }

                return stringOut.Trim();//去掉最后一个空
            }


            /// <summary>
            /// 将完整的帧分解到结构
            /// </summary>
            /// <param name="frame"></param>
            /// <returns></returns>
            public override void FetchFrame(string frame)
            {
                if (frame == null || frame == string.Empty)
                    return;
                if (string.IsNullOrEmpty(udpCAddr))
                    FetchNormalFrame(frame);
                else
                    FetchUDPFrame(frame);
            }


            /// <summary>
            /// 分解普通帧
            /// </summary>
            /// <param name="frame"></param>
            private void FetchNormalFrame(string frame)
            {
                try
                {
                    Head = frame.Substring(0, 2);  //去掉帧头
                    if (frame.Length <= 2)
                        return;
                    frame = frame.Substring(2);

                    FormatL.AnalizeData(ref frame);    //解析格式长度域               

                    Tail = frame.Substring(frame.Length - 2);  //去掉帧尾
                    frame = frame.Substring(0, frame.Length - 2);

                    FCS = frame.Substring(frame.Length - 4);   //去帧尾校验
                    FCS = ProtocolRelated.ChangeAddress(FCS);
                    frame = frame.Substring(0, frame.Length - 4);

                    Addr.AnalizeData(ref frame);  //解析 地址域
                    string errinfo = string.Empty;
                    C.AnalizeData(ref frame, ref errinfo); //解析控制域

                    HCS = string.Empty;

                    if (ExistHCS())
                    { //如果存在帧头校验
                        HCS = frame.Substring(0, 4);  //帧头校验
                        HCS = ProtocolRelated.ChangeAddress(HCS);
                        frame = frame.Substring(4);
                    }

                    if (frame.StartsWith(SLLCHead))  //返回命令LLC帧头
                    {
                        LLCHead = SLLCHead;
                        frame = frame.Substring(SLLCHead.Length);
                    }
                    else
                        if (frame.StartsWith(CLLCHead))  //返回命令LLC帧头
                        {
                            LLCHead = CLLCHead;
                            frame = frame.Substring(CLLCHead.Length);
                        }


                    ApduData = frame; //链路用户数据 APDU                  
                }
                catch
                {

                }
            }

            /// <summary>
            /// 分解47协议UDP返回帧
            /// </summary>
            /// <param name="frame"></param>
            private void FetchUDPFrame(string frame)
            {
                try
                {
                    udpVer = frame.Substring(0, 4);  //版本号
                    frame = frame.Substring(4);

                    udpCAddr = frame.Substring(0, 4); //UDP客户端地址
                    frame = frame.Substring(4);

                    udpSAddr = frame.Substring(0, 4);   //UDP服务端地址
                    frame = frame.Substring(4);

                    string slen = frame.Substring(0, 4);  //数据长度
                    frame = frame.Substring(4);

                    int ilen = Convert.ToInt32(slen, 16);                    
                    ApduData = frame.Substring(0, ilen * 2);  //链路用户数据 APDU  

                }
                catch
                {

                }
            }


            private bool ExistHCS()
            {
                // 2:控制 4:FCS 2：格式长度域 >4:4字符HCS,还存在信息字符
                return FormatL.L_lenData * 2 - Addr.SAddr_LOGIC.Length - Addr.CAddr_LOGIC.Length - 8 > 4;
            }
            /// <summary>
            /// 添加格式信息
            /// </summary>
            /// <param name="arghments"></param>
            public override void AddInformation(System.Collections.Hashtable arghments)
            {
                throw new NotImplementedException();
            }


            /// <summary>
            /// 添加解析格式
            /// </summary>
            /// <param name="objformat"></param>
            public override void AddFormat(object objformat)
            {
                // this.Apdu.clientApdu.AddObAttribute((ObAttribute)objformat);
            }

        }


        public class TProtocol62056 : PtlBase
        {
            public TFormat62056 ptlformat;
            public int RRR = 0;   //为接收帧计数， hxh 2020-1-7 只在解析时返回是I帧时才更新接收计数器,其他地方不更新,只取
            public int SSS = -1;   //为发送帧计数 ,发送I帧时都更新计数器

            public TProtocol62056()
            {
                ptlinfo = new PtlInformation();
                ptlformat = new TFormat62056();
            }

            /// <summary>
            /// 获取新的发送计数
            /// </summary>
            /// <returns></returns>
            public void GetNewSendCount()
            {
                SSS++;
                if (SSS > 7)
                    SSS = 0;
            }

            /// <summary>
            /// 获取新的接收计数
            /// </summary>
            /// <returns></returns>
            public void GetNewRecCount()
            {
                RRR++;
                if (RRR > 7)
                    RRR = 0;
            }

            //获取数据域，用于有后续帧时将所有数据域拼起来 
            public override string GetData()
            {
                return ptlformat.ApduData;
            }

            //获取真实数据域，通常指解密后的数据
            public override string GetRealData()
            {
                string rs = string.Empty;
                Encryption encryption = ptlformat.Apdu.encryption;

                if (!string.IsNullOrEmpty(encryption.PlaintData))  //encryption.IfEncrypt() && 
                    rs = encryption.PlaintData;

                return rs;
            }

            //设置数据域，用于将拼起来的数据域拿回来
            public override void SetData(string sdata)
            {
                ptlformat.ApduData = sdata;
            }

            
            public override int ResolveFrame(string recframe, ref string errinfo)
            {
                int iresult = 0;
                try
                {
                    ptlformat.FetchFrame(recframe);
                    base.ptlinfo.Frame = recframe; //原始帧 

                    if (ptlformat.C.C_FrameType == EnuFrameType.I)  //hxh 2020-1-7 返回是I帧时才更新接收计数器
                        this.GetNewRecCount();

                    //errinfo = CompareFrame(); //比较发送帧与接收帧是否匹配                                
                    //if (!string.IsNullOrEmpty(errinfo)) return -1;

                    base.ptlinfo.ContinueOrder = string.Empty;
                    //续抄指令  链路层分帧
                    if (ptlformat.FormatL.F_SPLIT == EnuSPLIT.split) //分帧标志为1  有后续帧
                    {
                        //在这里生成续抄指令
                        string continueorder = string.Empty;

                        TFormat62056 newptlformat = new TFormat62056();
                        newptlformat.Addr.SAddr_High = ptlformat.Addr.SAddr_High;
                        newptlformat.Addr.SAddr_Lower = ptlformat.Addr.SAddr_Lower;
                        newptlformat.Addr.SAddr_LEN = ptlformat.Addr.SAddr_LEN;
                        newptlformat.Addr.CAddr = ptlformat.Addr.CAddr;

                        newptlformat.C.C_FrameType = EnuFrameType.RR;
                        newptlformat.C.RRR = this.RRR;// ptlformat.C.RRR;     //hxh 2020-1-7 计数器单独计数                        

                        newptlformat.C.SSS = this.SSS;// ptlformat.C.SSS;
                      
                        ptlformat.LastC = newptlformat.C;                        

                        continueorder = Get62056Order(newptlformat, "", ref errinfo);
                      
                        base.ptlinfo.ContinueOrder = continueorder;
                        base.ptlinfo.DataName = ("续抄指令(链路层)");

                        //存储链路层分帧临时数据
                        ptlinfo.AddTmpData("LinkSplit", ptlformat.ApduData);  //shaunwang 2018-7-12
                    }
                    else  //获取所有链路层临时数据
                    {
                        ptlformat.ApduData = ptlinfo.GetTmpData("LinkSplit") //shaunwang 2018-7-12
                                           + ptlformat.ApduData;
                        ptlinfo.RemoveTmpData("LinkSplit");
                        if (ptlformat.LastC != null)
                        {
                            ptlformat.C = ptlformat.LastC;                        
                            ptlformat.C.C_FrameType = EnuFrameType.I;
                            ptlformat.LastC = null;
                        }
                    }

                    iresult = 1;
                }
                catch (Exception ex)
                {
                    errinfo = ex.Message;
                    iresult = -1;
                }
                return iresult;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="RWflag">读写标识</param>
            /// <param name="maxlength">链路用户数据最大长度(字节数)，超过则分帧</param>
            /// <param name="errinfo"></param>
            /// <returns></returns>
            public override string CreateOrder(string RWflag, int maxlength, ref string errinfo)  //生成指令
            {
                return CreateRandom(RWflag, null, maxlength, ref errinfo);
            }


            public override string CreateRandom(string RWflag, string pardata, int maxlength, ref string errinfo)  //生成任意指令
            {
                string orderstr = string.Empty;
                try
                {
                    string parameter = "";
                    if (pardata == null)  //未传入自定义数据域，需要生成   
                        parameter = ptlformat.Apdu.RequestApdu(ref errinfo);
                    else
                        parameter = pardata;

                    ptlformat.ApduData = parameter;  // 总的APDU数据
                    if (errinfo != string.Empty)
                        return orderstr;

                    if (!string.IsNullOrEmpty(ptlformat.udpCAddr))  //47协议 udp模式
                    {
                        return Get47PtlOrder(ptlformat);
                    }


                    string[] parlst = parameter.Split(',');
                    for (int p = 0; p < parlst.Length; p++)
                    {
                        string parstr = parlst[p];
                        if (p>0 && string.IsNullOrEmpty(parstr)) 
                            continue;

                        TFormat62056 newptlformat = new TFormat62056();
                        newptlformat.Apdu = ptlformat.Apdu;
                        newptlformat.Addr.SAddr_Lower = ptlformat.Addr.SAddr_Lower;
                        newptlformat.Addr.SAddr_High = ptlformat.Addr.SAddr_High;
                        newptlformat.Addr.SAddr_LEN = ptlformat.Addr.SAddr_LEN;
                        newptlformat.Addr.CAddr = ptlformat.Addr.CAddr;
                        newptlformat.C.C_FrameType = ptlformat.C.C_FrameType;
                        //newptlformat.C.SSS = ptlformat.C.SSS;
                        //newptlformat.C.RRR = ptlformat.C.RRR;                       

                        if (maxlength > 0 && parstr.Length > maxlength * 2)
                        {
                            string splitF; //分帧格式域
                            //这里处理生成链路层分帧指令,指令间以逗号分隔  未验证                           

                            // int splitNo = 0;  //分帧序号 
                            for (int i = 0; i < parstr.Length; i += maxlength * 2)
                            {
                                newptlformat.FormatL.F_SPLIT = EnuSPLIT.split;                               
                                if (i + maxlength * 2 >= parstr.Length)  //最后一帧
                                    newptlformat.FormatL.F_SPLIT = EnuSPLIT.end;

                                string datastr;
                                try
                                {
                                    datastr = parstr.Substring(i, maxlength * 2);
                                }
                                catch
                                {
                                    datastr = parstr.Substring(i);
                                }
                                this.GetNewSendCount();// 多帧时发送帧加1                               
                                newptlformat.C.SSS = this.SSS;
                                newptlformat.C.RRR = this.RRR;    //链路层的分帧返回的是RR帧，所以接收计数不加                          
                                orderstr += Get62056Order(newptlformat, datastr, ref errinfo)
                                          + ",";
                               
                                //newptlformat.C.GetNewSendCount();
                                //newptlformat.C.GetNewRecCount();// 多帧时发送和接收帧都加1


                            }

                        }
                        else
                        {
                            if(newptlformat.C.C_FrameType == EnuFrameType.I)                            
                                this.GetNewSendCount();// 多帧时发送帧加1
                            newptlformat.C.SSS = this.SSS;
                            newptlformat.C.RRR = this.RRR;
                            orderstr += Get62056Order(newptlformat, parstr, ref errinfo)
                                     + ",";
                            this.GetNewRecCount();  //多帧时多条命令同时生成，隐含的会收到I帧，接收计数加1才能生成后续正确命令；如果为单帧，则在解析时会重新赋值
                            //newptlformat.C.GetNewSendCount();
                            //newptlformat.C.GetNewRecCount();// 多帧时发送和接收帧都加1

                        }

                        ptlformat = newptlformat;
                    }
                    if (orderstr.EndsWith(","))
                        orderstr = orderstr.Substring(0, orderstr.Length - 1);

                }
                catch (Exception e)
                {
                    errinfo = e.Message;
                }
                return orderstr;
            }


            public override string CreateNextOrder(ref string errinfo)  //生成续抄指令
            {
                return "";
            }


            public override int AnalizeFrame(ref string errinfo)  //解析
            {
                int iresult = 0;
                try
                {
                    //在这里处理应用层分帧                    
                    string nowdata = ptlformat.ApduData;  //数据域
                   
                    iresult = ptlformat.Apdu.ResponseApdu(nowdata, ref errinfo);
                    if (iresult < 0)  //解析失败
                        return iresult;
                    
                    bool finished = ptlformat.Apdu.finished; //末帧标志　默认true//clientApdu
                    base.ptlinfo.AnaDone = finished;  //本次通信已解析

                    if (!finished)  //不是末帧
                    {
                        //存储链路层分帧临时数据
                        ptlinfo.AddTmpData("ApplySplit", ptlformat.Apdu.RawData); //shaunwang 2018-7-12    

                        TFormat62056 newptlformat = new TFormat62056();  //用于生成指令
                        newptlformat.Addr.SAddr_Lower = ptlformat.Addr.SAddr_Lower;
                        newptlformat.Addr.SAddr_High = ptlformat.Addr.SAddr_High;
                        newptlformat.Addr.SAddr_LEN = ptlformat.Addr.SAddr_LEN;
                        newptlformat.Addr.CAddr = ptlformat.Addr.CAddr;
                        newptlformat.Apdu.ApduSize = ptlformat.Apdu.ApduSize;
                        newptlformat.C.C_FrameType = ptlformat.C.C_FrameType;
                        newptlformat.Apdu.frameseq = ptlformat.Apdu.frameseq;
                      
                        this.GetNewSendCount();
                        newptlformat.C.SSS = this.SSS;
                        newptlformat.C.RRR = this.RRR;

                        newptlformat.Apdu.rwflag = ptlformat.Apdu.rwflag;
                        newptlformat.Apdu.encryption = ptlformat.Apdu.encryption;
                        if (ptlformat.Apdu.rwflag == ClientApduSel.GETRequest)
                            newptlformat.Apdu.rwtype = GetRRMode.GetNext.ToString();
                        else if (ptlformat.Apdu.rwflag == ClientApduSel.ActionRequest)
                            newptlformat.Apdu.rwtype = ActionRRMode.ActionPblock.ToString();

                        newptlformat.udpCAddr = ptlformat.udpSAddr;   //返回帧的服务端就是软件
                        newptlformat.udpSAddr = ptlformat.udpCAddr;   //返回帧的客户端对软件来说就是服务端
                        
                        string parameter = newptlformat.Apdu.RequestApdu(ref errinfo);

                        string errorder = "";
                        string neworder = "";
                        newptlformat.ApduData = parameter;  // 总的APDU数据
                        if (!string.IsNullOrEmpty(newptlformat.udpCAddr))  //47协议 udp模式
                        {
                            neworder = Get47PtlOrder(newptlformat);
                        }
                        else
                            neworder = Get62056Order(newptlformat, parameter, ref errorder);

                        if (errorder != "")
                        {
                            errinfo = ("生成应用层续抄指令失败:") + errorder;
                            return -2;
                        }
                        base.ptlinfo.ContinueOrder = neworder;
                        base.ptlinfo.DataName = "应用层续抄" + (Convert.ToInt64(ptlformat.Apdu.frameseq) + 1).ToString();

                        iresult = 1;
                    }
                    else if (ptlformat.Apdu.frameseq > 0)
                    {
                        string Data = ptlinfo.GetTmpData("ApplySplit") //shaunwang 2018-7-12
                                    + ptlformat.Apdu.RawData;

                        if (ptlformat.Apdu.ResMode == ServerApduSel.Generalblocktransfer)
                            iresult = ptlformat.Apdu.ResponseApdu(Data, ref errinfo);
                        else
                        {
                           // if (ptlformat.Apdu.ResMode >= ServerApduSel.gloGetResponse)
                                ptlformat.Apdu.encryption.PlaintData = Data;
            
                            iresult = ptlformat.Apdu.AnalizeData(Data, ref errinfo);
                        }
                        base.ptlinfo.AnaDone = true;
                    }                  
                }
                catch (Exception ex)
                {
                    errinfo = ex.Message;
                    iresult = -1;
                }
                return iresult;
            }


            /// <summary>
            /// 从收到的返回帧中获取正确格式的帧  多个帧用,分割
            /// </summary>
            /// <param name="aframe">原始数据</param>
            /// <param name="errinfo">错误信息</param>
            /// <returns>正确帧</returns>
            public override string GetCorrectFrameLst(string aframe, ref string errinfo)
            {
                return base.GetCorrectFrameLst(aframe, ref errinfo);
            }



            /// <summary>
            /// 从收到的返回帧中获取正确格式的帧，过滤掉主动上传的
            /// </summary>
            /// <param name="aframe">原始数据</param>
            /// <param name="errinfo">错误信息</param>
            /// <returns>不包含主动上传的正确帧</returns>
            public override string GetFrameWithoutUpload(ref string aframe, ref string errinfo)  //
            {
                return GetCorrectFrame(aframe, ref errinfo);
            }

            /// <summary>
            /// 获取正确的帧
            /// </summary>
            /// <param name="aframe">原始数据</param>
            /// <param name="errinfo">错误信息</param>
            /// <returns>正确帧</returns>
            public override string GetCorrectFrame(string aframe, ref string errinfo)
            {
                try
                {
                    int minlength = 8;  //无效帧定义为没有被两个标志正确界定的帧，或太短（在用16位FCS标志间短于四个字节）的帧
                    aframe = aframe.ToUpper();
                    string FrameStr = string.Empty;
                    if (aframe.Length < minlength)
                    {
                        if (errinfo == string.Empty)
                            errinfo = "帧长度过短";
                        return FrameStr;
                    }

                    int position = aframe.IndexOf(frametail);
                    if (position < 0)
                    {
                        if (errinfo == string.Empty)
                            errinfo = "无帧尾";
                        return FrameStr;
                    }

                    position = aframe.IndexOf(framehead);
                    if (position < 0)
                    {
                        if (errinfo == string.Empty)
                            errinfo =  "无帧头";
                        return FrameStr;
                    }

                    string tmpstr = aframe;
                    string[] arraystr = null;
                    while (position >= 0 && tmpstr.Length >= minlength)
                    {
                        tmpstr = tmpstr.Substring(position);
                        if (tmpstr.Length < minlength)
                        {
                            if (errinfo == string.Empty)
                                errinfo =  "帧长度过短";
                            return FrameStr;
                        }
                        if (tmpstr.Length % 2 != 0)
                        {
                            if (errinfo == string.Empty)
                                errinfo = "无帧头";
                            tmpstr = tmpstr.Substring(1);//去掉开头多余的字节
                            position = tmpstr.IndexOf(framehead);
                            continue;
                        }

                        bool havetail = false;
                        arraystr = new string[tmpstr.Length / 2];
                        for (int i = 0; i < tmpstr.Length; i += 2)
                        {
                            arraystr[i / 2] = tmpstr.Substring(i, 2);
                            if (arraystr[i / 2] == frametail)
                                havetail = true;
                        }

                        if (!havetail)
                        {
                            errinfo = "无帧尾";
                            return FrameStr;
                        }
                        else
                            break;
                    }

                    if (position < 0)
                    {
                        if (errinfo == string.Empty)
                            errinfo = "无帧头";
                        return FrameStr;
                    }

                    if (arraystr == null || arraystr.Length < minlength / 2)
                    {
                        return FrameStr;
                    }

                    //从原始帧中取出数据长度
                    int dataL;
                    try
                    {
                        string slength = arraystr[1] + arraystr[2];
                        slength = MyConvert.HexToBin(slength).PadLeft(16, '0');  //转为二进制
                        slength = slength.Substring(5);  //取后面的11位
                        dataL = Convert.ToInt32(MyConvert.BinToDec(slength));
                    }
                    catch
                    {
                        tmpstr = tmpstr.Substring(2);//去掉帧头
                        return GetCorrectFrame(tmpstr, ref errinfo);
                    }



                    //判断结尾是不是
                    if ((dataL + 2) * 2 > tmpstr.Length)
                    {
                        if (errinfo == string.Empty)
                            errinfo = "数据长度错";

                        tmpstr = tmpstr.Substring(2);//去掉帧头
                        return GetCorrectFrame(tmpstr, ref errinfo);
                    }
                    else
                    {
                        if (arraystr[dataL + 2 - 1] == frametail)  //帧尾正确 
                        {
                            for (int i = 0; i < dataL + 2; i++)
                                FrameStr += arraystr[i];
                            string FCSInFrame = arraystr[dataL + 2 - 2] + arraystr[dataL + 2 - 3];
                            if (FCSInFrame == Check.GetHFCS(FrameStr.Substring(2, FrameStr.Length - 8))) //校验正确
                            {
                                errinfo = string.Empty;

                                //判断一下HCS
                                try
                                {
                                    ptlformat.FetchFrame(FrameStr);

                                    string HCSInFrame = ptlformat.HCS;
                                    HCSInFrame = ProtocolRelated.ChangeAddress(HCSInFrame);
                                    if (!string.IsNullOrEmpty(HCSInFrame))
                                    {
                                        int llcpos = FrameStr.IndexOf(HCSInFrame);//FrameStr.IndexOf(SLLCHead);

                                        string calcHCS = Check.GetHFCS(FrameStr.Substring(2, llcpos - 2));
                                        calcHCS = ProtocolRelated.ChangeAddress(calcHCS);
                                        if (HCSInFrame != calcHCS)
                                        {
                                            errinfo = "帧头校验错";
                                            tmpstr = tmpstr.Substring(2);//去掉开头的标志
                                            return GetCorrectFrame(tmpstr, ref errinfo);
                                        }
                                    }

                                }
                                catch (Exception ex)
                                {
                                    errinfo = "头校验错：" + ex.Message;
                                    tmpstr = tmpstr.Substring(2);//去掉开头的68
                                    return GetCorrectFrame(tmpstr, ref errinfo);
                                }


                                return FrameStr;
                            }
                            else   //校验和不正确
                            {
                                errinfo = "帧校验错";
                                tmpstr = tmpstr.Substring(2);//去掉开头的68
                                return GetCorrectFrame(tmpstr, ref errinfo);
                            }
                        }
                        else   //帧尾不正确
                        {
                            errinfo = "数据长度错";

                            tmpstr = tmpstr.Substring(2);//去掉开头的68
                            return GetCorrectFrame(tmpstr, ref errinfo);
                        }

                    }
                }
                catch (Exception ex)
                {
                    if (errinfo == string.Empty)
                        errinfo = "未知错误:" + ex.Message;
                    return string.Empty;
                }
            }

            /// <summary>
            /// 获取设参结果
            /// </summary>
            /// <returns>返回null或"0"表示成功，否则返回错误信息</returns>
            public override string GetResult()  
            {
                string rs = "";

                List<CosemObject> objLst = ptlformat.Apdu.OIList;  //解析后的对象列表

                bool havefailed = false;  //是否有失败的
                for (int i = 0; i < objLst.Count; i++)
                {
                    if (ptlformat.Apdu.rwflag == ClientApduSel.DLConnectRequest && objLst[i].result == ((int)DLLConnResult.NOK).ToString())
                        rs += "0";
                    else
                    {
                        if (objLst[i].result == null || objLst[i].result == "0")  //errinfo是程序异常错误,oiobj.result是解析帧结果,0是成功,其他为帧异常错误
                            rs += "0";
                        else
                        {
                            rs += objLst[i].result;
                            havefailed = true;  //有失败的
                        }
                        if (i < objLst.Count - 1)
                            rs += "&";
                    }
                }
                if (string.IsNullOrEmpty(rs) || !havefailed)  //如果没有失败的就返回一个0
                    rs = "0";
                return rs;
            }


            /// <summary>
            /// 获取解析后的值，所有值拼起来，逗号分隔
            /// </summary>
            /// <returns></returns>
            public override string GetReadValue() 
            {
                //从ptlformat获取所有解析后的值，拼起来
                string rs = string.Empty;
                List<CosemObject> objLst = ptlformat.Apdu.OIList;  //解析后的对象列表
                for (int i = 0; i < objLst.Count; i++)
                {
                    if (objLst[i].Tag is ProNodeBase && !(objLst[i].Tag as ProNodeBase).Availability)  //不可见的
                        continue;
                    rs += GetValueFromObj(objLst[i].DataNode)
                        + ","; 
                }
                if (rs.EndsWith(","))
                    rs = rs.Substring(0, rs.Length - 1);
                return rs;
            }



            /// <summary>
            /// 从对象中获取数据
            /// </summary>
            /// <param name="oiobj"></param>
            /// <returns></returns>
            private string GetValueFromObj(ElementData datanode)
            {
                string rs = datanode.ReadValue;

                //if (!string.IsNullOrEmpty(datanode.ShowFormat))
                //    rs = PtlCommunal.Explaindata1(rs, PtlCommunal.InitFormat(datanode.ShowFormat));

                //if (!string.IsNullOrEmpty(datanode.Display))
                //    rs = PtlCommunal.Explaindata2(rs, datanode.Display);

                if (datanode.eleNodeList.Count > 0)
                {
                    rs = string.Empty;//rs += ",";
                    for (int i = 0; i < datanode.eleNodeList.Count; i++)
                    {
                        rs += GetValueFromObj(datanode.eleNodeList[i])
                            + ","; 
                    }
                    if (rs.EndsWith(","))
                        rs = rs.Substring(0, rs.Length - 1); 
                }
                return rs;
            }

            

            /// <summary>
            /// 获取解析前的值，所有值拼起来，逗号分隔
            /// </summary>
            /// <returns></returns>
            public override string GetFrameValue()
            {
                //从ptlformat获取所有解析前的值，拼起来
                string rs = string.Empty;
                List<CosemObject> objLst = ptlformat.Apdu.OIList;  //解析后的对象列表
                for (int i = 0; i < objLst.Count; i++)
                {
                    rs += GetFrameValueFromObj(objLst[i].DataNode);
                    if (i < objLst.Count - 1)
                        rs += "&";
                }
                return rs;
            }


            /// <summary>
            /// 从对象中获取数据
            /// </summary>
            /// <param name="oiobj"></param>
            /// <returns></returns>
            private string GetFrameValueFromObj(ElementData datanode)
            {
                string rs = datanode.FrameValue == null ? string.Empty : datanode.FrameValue;
                return rs;
            }


            /// <summary>
            /// 判断当前协议对象是否需要返回
            /// </summary>
            /// <returns></returns>
            public override bool NeedReturn()
            {
                return ptlformat.NeedReturn();
            }


            /// <summary>
            /// 生成47协议命令
            /// </summary>
            /// <param name="ptlformat"></param>
            /// <returns></returns>
            private string Get47PtlOrder(TFormat62056 ptlformat)
            {                
                double ilen = ptlformat.ApduData.Length / 2;
                string orderstr = ptlformat.udpVer
                                + ptlformat.udpCAddr
                                + ptlformat.udpSAddr
                                + MyConvert.DecToHex(ilen.ToString(), 4)
                                + ptlformat.ApduData;
                return orderstr;

            }



            /// <summary>
            /// 生成指令
            /// </summary>
            /// <param name="meter"></param>
            /// <param name="C"></param>
            /// <param name="parameter"></param>
            private string Get62056Order(TFormat62056 ptlformat, string parameter, ref string errinfo)
            {
                StringBuilder stbStr = new StringBuilder();
                stbStr.Append(framehead);

                //地址域
                string addr = ptlformat.Addr.GetFormatValue(ref errinfo);
                if (string.IsNullOrEmpty(addr))
                    return string.Empty;

                if (!ptlformat.NeedReturn())
                    ptlformat.C.PBit = EnuPBit.PNoRE;
                //控制码域
                string C = ptlformat.C.GetFormatValue();

                //帧格式，包括长度
                string formatL = ptlformat.FormatL.GetFormatValue(addr, parameter,ptlformat.C);
                stbStr.Append(formatL);
                stbStr.Append(addr);
                stbStr.Append(C);

                if (!string.IsNullOrEmpty(parameter))  //存在用户数据域
                {
                    string HCS = Check.GetHFCS(stbStr.ToString().Substring(2));
                    HCS = ProtocolRelated.ChangeAddress(HCS);
                    stbStr.Append(HCS);
                    if (ptlformat.C.C_FrameType != EnuFrameType.SNRM)  //建立链路层连接时有用户数据，但无LLC帧头
                        stbStr.Append(CLLCHead);
                    stbStr.Append(parameter);
                }
                string FCS = Check.GetHFCS(stbStr.ToString().Substring(2));
                FCS = ProtocolRelated.ChangeAddress(FCS);
                stbStr.Append(FCS);
                stbStr.Append(frametail);
                return stbStr.ToString();
            }


            /// <summary>
            /// 比较收发帧是否匹配
            /// </summary>      
            /// <returns>匹配结果，如果为空表示匹配正确</returns>
            //public string CompareFrame()
            //{
            //    return CompareFrame(base.ptlinfo.SendFrame, base.ptlinfo.Frame);
            //}

            /// <summary>
            /// 比较收发帧是否匹配
            /// </summary>
            /// <param name="sendstr">发送帧</param>
            /// <param name="recstr">接收帧</param>
            /// <param name="WRflag">读写标识 R?W?</param>
            /// <param name="datalength">预计返回数据长度，如果为-1表示不判长度</param>
            /// <returns>匹配结果，如果为空表示匹配正确</returns>
            public override string CompareFrame(string sendstr, string recstr, string WRflag, int datalength)
            {
                if (string.IsNullOrEmpty(sendstr))
                    return string.Empty;

                if (!sendstr.StartsWith(framehead) || !recstr.StartsWith(framehead))
                    return string.Empty;

                try
                {                    
                    string errinfo = string.Empty;
                    TFormat62056 sendframe = new TFormat62056();
                    sendframe.FetchFrame(sendstr);
                    TFormat62056 recframe = new TFormat62056();
                    recframe.FetchFrame(recstr);

                    //比较表地址
                    int sends = sendframe.Addr.SAddr_Lower;
                    int recs = recframe.Addr.SAddr_Lower;
                    int Bordcase = 0;

                    switch (Convert.ToString(sends,16).Length)
                    {  //广播地址不判断
                        case 1:
                        case 2: Bordcase = Convert.ToInt32("7F", 16); break;
                        case 3:                       
                        case 4: Bordcase = Convert.ToInt32("3FFF",16); break;
                    }
                    if (sends != Bordcase && sends != recs)
                        return "返回表地址不符";

                    if (!CheckResFrameType(sendframe.C.C_FrameType, recframe.C.C_FrameType))
                    {
                        return "返回帧的类型不正确";
                    }

                    //if (recframe.C.C_FrameType==EnuFrameType.FRMR)
                    //{
                    //    return "返回的帧类型为拒绝接收";
                    //}

                }
                catch
                {

                }
                return string.Empty;



            }

            /// <summary>
            /// 校验命令帧的返回类型
            /// </summary>
            /// <param name="cmdFrameType"></param>
            /// <returns></returns>
            private bool CheckResFrameType(EnuFrameType cmdFrameType, EnuFrameType resFrameType)
            {

                switch (cmdFrameType)
                {
                    case EnuFrameType.I:
                        return resFrameType == EnuFrameType.I ? true : false; break;
                    case EnuFrameType.RR:
                        if (resFrameType == EnuFrameType.RR || resFrameType == EnuFrameType.I)
                            return true;
                        break;
                    case EnuFrameType.RNR:
                        return resFrameType == EnuFrameType.RNR ? true : false; break;
                    case EnuFrameType.SNRM:
                        return resFrameType == EnuFrameType.UA ? true : false; break;
                    case EnuFrameType.DISC:
                        if (resFrameType == EnuFrameType.DM || resFrameType == EnuFrameType.UA)
                            return true;
                        break;
                    case EnuFrameType.UI:
                        return resFrameType == EnuFrameType.UI ? true : false; break;
                }
                if (resFrameType == EnuFrameType.FRMR) return true;

                return false;
            }

           
            //计算校验
            public override string CalcCS(string sdata)
            {
                string calcstr = string.Empty;
                if (string.IsNullOrEmpty(sdata))
                    return string.Empty;
                try
                {
                    calcstr = Check.GetHFCS(sdata);
                    calcstr = ProtocolRelated.ChangeAddress(calcstr);
                }
                catch
                {

                }
                return calcstr;
            }

            ////判断返回结果对象中是否有错误,返回第一个有错的序号. 否则返回-1
            //public List<ObAttribute> CheckIOLstResult()
            //{
            //    List<ObAttribute> RightOILst = new List<ObAttribute>();
            //    List<ObAttribute> OILst = this.ptlformat.Apdu.clientApdu.OIList;
            //    for (int i = 0; i < OILst.Count; i++)
            //    {
            //        if (OILst[i].result == "0")
            //            RightOILst.Add(OILst[i]);
            //    }
            //    return RightOILst;
            //}

            //获取启动标志  1:上位机发起   0:表发起  shaunwang 2019-8-19
            public override string GetPRM()
            {
                return "0";
            }
        }

    }
}